package io.kiki.sba.registry.server.shared.slot;


import io.kiki.sba.registry.common.model.slot.Slot;
import io.kiki.sba.registry.common.model.slot.Slots;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;


public class SlotsUtils {

    private static final Logger logger = LoggerFactory.getLogger(SlotsUtils.class);

    public static Map<String, Integer> getSlotsLeaderCount(Slots slots) {
        Map<String, Integer> leaderCounter = new HashMap<>(slots.getSlotIdToSlotMap().size());
        for (Map.Entry<Integer, Slot> entry : slots.getSlotMap().entrySet()) {
            Slot slot = entry.getValue();
            incrCount(leaderCounter, slot.getLeaderDataStoreNodeId());
        }
        return leaderCounter;
    }

    public static Map<String, Integer> getSlotsSlotCount(Slots slots) {
        Map<String, Integer> slotCounter = new HashMap<>(slots.getSlotIdToSlotMap().size());
        for (Map.Entry<Integer, Slot> entry : slots.getSlotMap().entrySet()) {
            Slot slot = entry.getValue();
            incrCount(slotCounter, slot.getLeaderDataStoreNodeId());
            for (String follower : slot.getFollowerDataStoreNodeIdSet()) {
                incrCount(slotCounter, follower);
            }
        }
        return slotCounter;
    }

    private static void incrCount(Map<String, Integer> counter, String dataServer) {
        Integer count = counter.get(dataServer);
        if (count == null) {
            count = 0;
        }
        counter.put(dataServer, count + 1);
    }

    public static boolean isValidSlots(Slots slots) {
        return checkNoDupLeaderAndFollowers(slots) && checkNoLeaderEmpty(slots);
    }

    public static boolean checkNoDupLeaderAndFollowers(Slots slots) {
        for (Map.Entry<Integer, Slot> entry : slots.getSlotMap().entrySet()) {
            Slot slot = entry.getValue();
            if (slot.getFollowerDataStoreNodeIdSet().contains(slot.getLeaderDataStoreNodeId())) {
                logger.error("[checkNoDupLeaderAndFollowers] slot[{}] leader and follower duplicates", slot);
                return false;
            }
        }
        return true;
    }

    public static boolean checkNoLeaderEmpty(Slots slots) {
        for (Map.Entry<Integer, Slot> entry : slots.getSlotMap().entrySet()) {
            Slot slot = entry.getValue();
            if (StringUtils.isEmpty(slot.getLeaderDataStoreNodeId())) {
                logger.error("[checkNoLeaderEmpty] slot[{}] empty leader", slot);
                return false;
            }
        }
        return true;
    }
}
